package com.xhlj.controller;

import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.codec.Base64;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xhlj.utils.RedisKey;
import com.xhlj.utils.Result;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Yzc
 * @description 下单接口，相应一个二维码给前端
 * @create 2024/3/22
 **/

@RestController()
@Slf4j
public class PayController {
    @Resource
    private Config config;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/pay")
    public Result pay(@RequestParam("subject") String subject, @RequestParam("totalAmount") String totalAmount, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        /*先凑合一下 就直接Username加上时间戳*/
        String outTrade = username + System.currentTimeMillis();
        Factory.setOptions(config);
        //TODO:调用支付宝的接口
        //TODO:订单编号、业务数据这里写死 订单编号：LS123qwe123
        AlipayTradePrecreateResponse payResponse = Factory.Payment.FaceToFace().preCreate(subject, outTrade, totalAmount);
        //参照官方文档响应示例，解析返回结果
        String httpBodyStr = payResponse.getHttpBody();
        JSONObject jsonObject = JSONObject.parseObject(httpBodyStr);
        String qrUrl = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();
//      QrCodeUtil.generate("https://www.baidu.com", config, new File("D:\\code.png"));
//        做支付宝请求取得用户名
        stringRedisTemplate.opsForValue().set(RedisKey.Alipay_prefex + outTrade, username);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        QrCodeUtil.generate(qrUrl, 300, 300, "png", outputStream);
        byte[] qrCodeBytes = outputStream.toByteArray();
        String base64Image = Base64.encodeBase64String(qrCodeBytes);
        HashMap<String, String> map = new HashMap<>();
        map.put("imageUrl", base64Image);
        map.put("outTrade", outTrade);
        return Result.ok(map);
    }

    /**
     * 给支付宝的回调接口, 有点问题,订单状态是拿不到的
     */
    @PostMapping("/notify")
    public void notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, String> params = new HashMap<>();
        //获取支付宝POST过来反馈信息，将异步通知中收到的待验证所有参数都存放到map中,outTradeNo
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (String name : parameterMap.keySet()) {
            String[] values = parameterMap.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
//            authentication.getName()
        //验签
        Boolean signResult = Factory.Payment.Common().verifyNotify(params);
        System.out.println("parameterMap:" + parameterMap.size() + signResult);
        if (signResult) {
            log.info("收到支付宝发送的支付结果通知");
            System.out.println("收到支付宝发送的支付结果通知");
            String out_trade_no = request.getParameter("out_trade_no");
            log.info("交易流水号：{}", out_trade_no);
            //交易状态
            String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
            //交易成功
            switch (trade_status) {
                case "TRADE_SUCCESS":
                    //支付成功的业务逻辑，比如落库，开vip权限等
                    log.info("订单：{} 交易成功", out_trade_no);
                    System.out.println("订单,交易成功");
                    break;
                case "TRADE_FINISHED":
                    log.info("交易结束，不可退款");
                    System.out.println("订单,不可退款");

                    //其余业务逻辑
                    break;
                case "TRADE_CLOSED":
                    log.info("超时未支付，交易已关闭，或支付完成后全额退款");
                    System.out.println("订单,超时未支付");

                    //其余业务逻辑
                    break;
                case "WAIT_BUYER_PAY":
                    log.info("交易创建，等待买家付款");
                    System.out.println("订单,交易创建");
                    //其余业务逻辑
                    break;
            }
            response.getWriter().write("success");   //返回success给支付宝，表示消息我已收到，不用重调
            stringRedisTemplate.opsForValue().set(RedisKey.Alipay_prefex + out_trade_no, trade_status);


        } else {
            response.getWriter().write("fail");   ///返回fail给支付宝，表示消息我没收到，请重试
        }
    }

    @GetMapping("pay/status")
    public Result getTradeStatus(String outTrade) {

        String status = stringRedisTemplate.opsForValue().get(RedisKey.Alipay_prefex + outTrade);
        return Result.ok(status);
    }

}

